"""
字体工具模块
提供随机字体选择功能
"""

import os
import random
from PIL import ImageFont, ImageDraw

def get_system_fonts():
    """
    获取系统中可用的字体列表
    
    Returns:
        list: 可用字体路径列表
    """
    font_paths = []
    
    # 常见字体目录
    if os.name == 'nt':  # Windows
        font_dirs = [
            os.path.expandvars(r'%WINDIR%\Fonts'),
            r'C:\Windows\Fonts'
        ]
    else:  # macOS and Linux
        font_dirs = [
            '/System/Library/Fonts',
            '/Library/Fonts',
            os.path.expanduser('~/Library/Fonts'),
            '/usr/share/fonts',
            os.path.expanduser('~/.fonts')
        ]
    
    common_font_names = [
        'arial.ttf', 'Arial.ttf', 'times.ttf', 'Times.ttf', 'courier.ttf', 'Courier.ttf',
        'helvetica.ttf', 'Helvetica.ttf', 'verdana.ttf', 'Verdana.ttf',
        'calibri.ttf', 'Calibri.ttf', 'cambria.ttc', 'Cambria.ttc',
        'simhei.ttf', 'simsun.ttc', 'fangzheng.ttf', 'heiti.ttf'
    ]
    
    # 检查常见字体文件
    for font_dir in font_dirs:
        if os.path.exists(font_dir):
            for font_name in common_font_names:
                font_path = os.path.join(font_dir, font_name)
                if os.path.exists(font_path):
                    font_paths.append(font_path)
    
    return font_paths

def get_random_font(font_size=40):
    """
    获取随机字体
    
    Args:
        font_size (int): 字体大小
        
    Returns:
        PIL.ImageFont: 随机选择的字体对象
    """
    try:
        # 获取系统字体
        system_fonts = get_system_fonts()
        
        if system_fonts:
            # 随机选择一个字体
            chosen_font = random.choice(system_fonts)
            return ImageFont.truetype(chosen_font, font_size)
        
        # 如果没有找到系统字体，尝试使用Pillow的默认字体
        return ImageFont.load_default()
        
    except Exception as e:
        print(f"加载随机字体时出错: {e}")
        # 最后的fallback
        try:
            return ImageFont.truetype("Arial", font_size)
        except:
            return ImageFont.load_default()

# 测试函数
def test_random_font():
    """
    测试随机字体功能
    """
    try:
        font = get_random_font(40)
        print(f"成功加载随机字体")
        return True
    except Exception as e:
        print(f"测试随机字体失败: {e}")
        return False

if __name__ == "__main__":
    test_random_font()
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
在视频上添加文本和图标
该脚本可以直接运行，用于在现有视频上叠加文本和图标
"""

import os
import sys
import base64
import random
import textwrap
from io import BytesIO

# 尝试导入moviepy.editor，如果失败则给出提示
try:
    from moviepy import VideoFileClip, CompositeVideoClip, ImageClip
    from moviepy.video.tools.drawing import color_gradient
    MOVIEPY_AVAILABLE = True
except ImportError as e:
    print(f"无法导入moviepy.editor: {e}")
    print("请确保已正确安装moviepy: pip install moviepy==2.2.1")
    MOVIEPY_AVAILABLE = False

# 尝试导入PIL，如果失败则给出提示
try:
    from PIL import Image, ImageDraw, ImageFont
    PIL_AVAILABLE = True
except ImportError as e:
    print(f"无法导入PIL: {e}")
    print("请确保已正确安装Pillow: pip install Pillow")
    PIL_AVAILABLE = False


def base64_to_temp_image(base64_string, prefix="team_logo"):
    """
    将base64字符串转换为临时图片文件并保存
    
    Args:
        base64_string (str): base64编码的图片数据
        prefix (str): 文件名前缀
        
    Returns:
        str: 保存的文件路径，如果失败则返回None
    """
    try:
        # 检查是否是有效的base64字符串
        if not base64_string or not base64_string.startswith('data:image'):
            return None
            
        # 解析base64数据
        header, encoded_data = base64_string.split(',', 1)
        file_extension = header.split('/')[1].split(';')[0]
        
        # 解码base64数据
        image_data = base64.b64decode(encoded_data)
        
        # 生成临时文件名
        filename = f"{prefix}_{random.randint(1000, 9999)}.{file_extension}"
        temp_dir = os.path.join(os.getcwd(), 'temp')
        os.makedirs(temp_dir, exist_ok=True)
        file_path = os.path.join(temp_dir, filename)
        
        # 保存图片文件
        with open(file_path, 'wb') as f:
            f.write(image_data)
            
        return file_path
    except Exception as e:
        print(f"Base64转换为图片文件失败: {e}")
        return None


def create_text_image(text, font_size=40, text_color=(255, 255, 255), stroke_color=(0, 0, 0), stroke_width=1, max_width=None, line_spacing=1.0):
    """
    使用PIL创建文本图像并返回ImageClip
    
    Args:
        text (str): 要绘制的文本
        font_size (int): 字体大小
        text_color (tuple): 文本颜色 (R, G, B)
        stroke_color (tuple): 描边颜色 (R, G, B)
        stroke_width (int): 描边宽度
        max_width (int): 最大宽度，超过此宽度将自动换行
        line_spacing (float): 行间距倍数，默认为1.0（无额外行距）
        
    Returns:
        PIL.Image: 生成的文本图像
    """
    if not PIL_AVAILABLE:
        return None
    
    # 创建一个较大的画布以容纳文本
    dummy_img = Image.new('RGB', (2000, 400), color=(0, 0, 0, 0))
    dummy_draw = ImageDraw.Draw(dummy_img)
    
    # 尝试使用支持Unicode的字体
    font = None
    try:
        # 优先使用Noto Color Emoji字体来更好地支持emoji
        noto_color_emoji_path = "C:\\Windows\\Fonts\\NotoColorEmoji.ttf"
        seguiemj_path = "C:\\Windows\\Fonts\\seguiemj.ttf"  # Segoe UI Emoji
        arialuni_path = "C:\\Windows\\Fonts\\ARIALUNI.TTF"
        segoeui_path = "C:\\Windows\\Fonts\\segoeui.ttf"
        noto_sans_paths = [
            "C:\\Windows\\Fonts\\NotoSans-Bold.ttf",
            "C:\\Windows\\Fonts\\NotoSans.ttf", 
            "C:\\Windows\\Fonts\\NotoSans-Regular.ttf"
        ]
        
        # 检查可用的字体，按优先级排序 (Noto Color Emoji优先)
        font_paths = [
            noto_color_emoji_path,
            seguiemj_path,
            arialuni_path,
            segoeui_path
        ] + noto_sans_paths
        
        # 尝试加载支持emoji的字体
        for font_path in font_paths:
            if os.path.exists(font_path):
                try:
                    font = ImageFont.truetype(font_path, font_size)
                    break
                except Exception as e:
                    print(f"加载字体 {font_path} 失败: {e}")
                    continue
        
        # 如果上述字体都不可用，尝试使用随机字体
        if font is None:
            try:
                from src.utils.font_utils import get_random_font
                font = get_random_font(font_size)
            except ImportError:
                print("无法导入font_utils模块，将使用默认字体")
                font = ImageFont.load_default()
    except Exception as e:
        print(f"加载字体失败: {e}，将使用默认字体")
        font = ImageFont.load_default()
    
    # 处理自动换行，使用textwrap模块和精确的文本宽度计算
    def get_text_width(text):
        """获取文本的实际宽度"""
        try:
            bbox = dummy_draw.textbbox((0, 0), text, font=font)
            return bbox[2] - bbox[0]
        except:
            try:
                width, _ = dummy_draw.textsize(text, font=font)
                return width
            except:
                # Fallback计算方法
                return len(text) * font_size * 0.6
    
    def wrap_text(paragraph, max_width):
        """根据最大宽度智能换行文本"""
        # 如果整段文本宽度小于最大宽度，直接返回
        if get_text_width(paragraph) <= max_width:
            return [paragraph]
        
        lines = []
        # 按空格分割单词
        words = paragraph.split(' ')
        current_line = ""
        
        for word in words:
            # 测试添加当前单词后的行宽
            test_line = (current_line + " " + word).strip()
            line_width = get_text_width(test_line)
            
            # 如果添加单词后超过最大宽度
            if line_width > max_width:
                # 如果当前行不为空，将其作为一行添加
                if current_line:
                    lines.append(current_line)
                    current_line = word
                else:
                    # 如果当前行为空但单个单词就超过宽度，则强制换行
                    # 这里使用textwrap对长单词进行分割
                    wrapped_word = textwrap.fill(word, width=max(1, int(max_width / (font_size * 0.6))))
                    word_lines = wrapped_word.split('\n')
                    lines.extend(word_lines[:-1])  # 添加除最后一行外的所有行
                    current_line = word_lines[-1]  # 最后一行成为新的当前行
            else:
                current_line = test_line
        
        # 添加最后一行
        if current_line:
            lines.append(current_line)
            
        return lines
    
    # 处理所有段落
    if max_width and font:
        lines = []
        for paragraph in text.split('\n'):
            wrapped_lines = wrap_text(paragraph, max_width)
            lines.extend(wrapped_lines)
    else:
        lines = text.split('\n')
    
    # 如果没有行，返回空图像
    if not lines:
        lines = ['']
    
    # 计算文本尺寸
    try:
        # 计算每行的高度
        line_heights = []
        for line in lines:
            bbox = dummy_draw.textbbox((0, 0), line, font=font)
            line_height = bbox[3] - bbox[1]
            line_heights.append(line_height)
        
        # 计算总高度，考虑行间距
        total_height = sum(line_heights)
        if len(lines) > 1:
            # 添加行间距
            default_line_height = max(line_heights) if line_heights else font_size
            extra_line_spacing = default_line_height * (line_spacing - 1.0)
            total_height += extra_line_spacing * (len(lines) - 1)
            
        # 计算最大宽度
        max_text_width = 0
        for line in lines:
            line_width = get_text_width(line)
            max_text_width = max(max_text_width, line_width)
            
        text_width = max_text_width
        text_height = total_height
    except:
        try:
            # fallback计算方法
            text_width, _ = dummy_draw.textsize("M", font=font)  # 单个字符宽度
            text_width *= max(len(line) for line in lines) if lines else 0
            
            line_height = font_size
            text_height = line_height * len(lines)
            if len(lines) > 1:
                extra_line_spacing = line_height * (line_spacing - 1.0)
                text_height += extra_line_spacing * (len(lines) - 1)
        except:
            # 最后的fallback，使用估算
            lines_count = len(lines)
            text_width = max_width if max_width else 800
            text_height = lines_count * font_size
            if lines_count > 1:
                extra_line_spacing = font_size * (line_spacing - 1.0)
                text_height += extra_line_spacing * (lines_count - 1)
    
    # 创建实际图像，增加额外空间以适应emoji
    img = Image.new('RGBA', (int(text_width) + stroke_width * 2 + 40, int(text_height) + stroke_width * 2 + 40), color=(0, 0, 0, 0))
    draw = ImageDraw.Draw(img)
    
    # 逐行绘制文本和描边，支持行间距
    default_line_height = font_size  # 默认行高
    
    try:
        # 获取更准确的行高
        sample_bbox = dummy_draw.textbbox((0, 0), "M", font=font)
        default_line_height = sample_bbox[3] - sample_bbox[1]
    except:
        pass
    
    extra_line_spacing = default_line_height * (line_spacing - 1.0)
    
    # 绘制描边
    if stroke_width > 0:
        for x_offset in range(-stroke_width, stroke_width + 1):
            for y_offset_range in range(-stroke_width, stroke_width + 1):
                # 逐行绘制描边
                current_y = stroke_width + 20
                for line_text in lines:
                    draw.text((stroke_width - x_offset + 20, current_y - y_offset_range), line_text, font=font, fill=stroke_color)
                    # 计算下一行的Y位置
                    try:
                        line_bbox = draw.textbbox((0, 0), line_text, font=font)
                        line_height = line_bbox[3] - line_bbox[1]
                    except:
                        line_height = default_line_height
                    current_y += line_height + extra_line_spacing
    
    # 绘制文本
    current_y = stroke_width + 20
    for line in lines:
        draw.text((stroke_width + 20, current_y), line, font=font, fill=text_color)
        # 计算下一行的Y位置
        try:
            line_bbox = draw.textbbox((0, 0), line, font=font)
            line_height = line_bbox[3] - line_bbox[1]
        except:
            line_height = default_line_height
        current_y += line_height + extra_line_spacing
    
    return img


def pil_image_to_temp_file(image, prefix="text_image"):
    """
    将PIL图像保存为临时文件并返回文件路径
    
    Args:
        image (PIL.Image): PIL图像对象
        prefix (str): 文件名前缀
        
    Returns:
        str: 临时文件路径
    """
    temp_dir = os.path.join(os.getcwd(), 'temp')
    os.makedirs(temp_dir, exist_ok=True)
    filename = f"{prefix}_{random.randint(1000, 9999)}.png"
    file_path = os.path.join(temp_dir, filename)
    
    image.save(file_path, 'PNG')
    return file_path


def add_text_and_logos_to_video(video_path, output_path, match_info):
    """
    在视频上添加文本和队伍图标
    
    Args:
        video_path (str): 原始视频路径
        output_path (str): 输出视频路径
        match_info (dict): 比赛信息，包含以下字段:
            - team_a: 球队A名称
            - team_b: 球队B名称
            - match_time: 比赛时间
            - copywriting: 文案
            - team_a_logo: 球队A图标(base64格式)
            - team_b_logo: 球队B图标(base64格式)
        
    Returns:
        bool: 是否成功
    """
    if not MOVIEPY_AVAILABLE or not PIL_AVAILABLE:
        print("缺少必要的依赖库，请检查moviepy和Pillow是否正确安装")
        return False
        
    temp_files = []  # 记录创建的临时文件，以便清理
        
    try:
        # 检查视频文件是否存在
        if not os.path.exists(video_path):
            print(f"视频文件不存在: {video_path}")
            return False
            
        # 加载视频
        video = VideoFileClip(video_path)
        width, height = video.size
        
        # 创建文本剪辑
        text_clips = []
        
        # 添加比赛标题 (球队A vs 球队B)
        title_text = f"{match_info['team_a']} vs {match_info['team_b']}"
        title_image = create_text_image(title_text, font_size=80, text_color=(255, 255, 255), stroke_color=(0, 0, 0), stroke_width=2)
        title_image_path = pil_image_to_temp_file(title_image, "title")
        temp_files.append(title_image_path)
        title_clip = ImageClip(title_image_path)
        title_clip = title_clip.set_position(('center', height // 8)).set_duration(video.duration)
        text_clips.append(title_clip)
        
        # 添加比赛时间
        time_text = match_info['match_time']
        time_image = create_text_image(time_text, font_size=60, text_color=(255, 255, 0), stroke_color=(0, 0, 0), stroke_width=1)
        time_image_path = pil_image_to_temp_file(time_image, "time")
        temp_files.append(time_image_path)
        time_clip = ImageClip(time_image_path)
        time_clip = time_clip.set_position(('center', height // 4)).set_duration(video.duration)
        text_clips.append(time_clip)
        
        # 添加文案
        copywriting = match_info['copywriting']
        copywriting_image = create_text_image(copywriting, font_size=40, text_color=(255, 255, 255), stroke_color=(0, 0, 0), stroke_width=1)
        copywriting_image_path = pil_image_to_temp_file(copywriting_image, "copywriting")
        temp_files.append(copywriting_image_path)
        copywriting_clip = ImageClip(copywriting_image_path)
        copywriting_clip = copywriting_clip.set_position(('center', height * 3 // 4)).set_duration(video.duration)
        text_clips.append(copywriting_clip)
        
        # 添加默认图片"telegram.png"
        try:
            telegram_image = Image.open("static/images/telegram.png")
            # 调整图片大小，使用较小的尺寸以匹配文本大小
            aspect_ratio = telegram_image.width / telegram_image.height
            new_height = 30  # 更小的高度
            new_width = int(new_height * aspect_ratio)
            telegram_image = telegram_image.resize((new_width, new_height))
            
            telegram_image_path = pil_image_to_temp_file(telegram_image, "telegram")
            temp_files.append(telegram_image_path)
            telegram_clip = ImageClip(telegram_image_path)
            telegram_clip = telegram_clip.set_position(('center', height - 60)).set_duration(video.duration)  # 放在底部上方60像素处
            text_clips.append(telegram_clip)
        except Exception as e:
            print(f"无法加载telegram.png: {e}")
            # 如果图片加载失败，仍然添加文本作为后备方案
            default_text = "✈️LUCKYFF8"
            default_image = create_text_image(default_text, font_size=30, text_color=(255, 255, 255), stroke_color=(0, 0, 0), stroke_width=1)  # 更小的字体
            default_image_path = pil_image_to_temp_file(default_image, "default")
            temp_files.append(default_image_path)
            default_clip = ImageClip(default_image_path)
            default_clip = default_clip.set_position(('center', height - 60)).set_duration(video.duration)  # 放在底部上方60像素处
            text_clips.append(default_clip)
        
        # 处理队伍图标
        logo_clips = []
        logo_size = 120
        
        if 'team_a_logo' in match_info and match_info['team_a_logo']:
            team_a_logo_path = base64_to_temp_image(match_info['team_a_logo'], "team_a_logo")
            if team_a_logo_path:
                temp_files.append(team_a_logo_path)
                try:
                    team_a_logo_clip = ImageClip(team_a_logo_path)
                    team_a_logo_clip = team_a_logo_clip.resize((logo_size, logo_size)).set_duration(video.duration)
                    # 添加一些动画效果
                    team_a_logo_clip = team_a_logo_clip.set_position(
                        lambda t: (width // 4 - logo_size // 2, height * 5 // 8)
                    )
                    logo_clips.append(team_a_logo_clip)
                except Exception as e:
                    print(f"处理队伍A视频图标时出错: {e}")
        
        if 'team_b_logo' in match_info and match_info['team_b_logo']:
            team_b_logo_path = base64_to_temp_image(match_info['team_b_logo'], "team_b_logo")
            if team_b_logo_path:
                temp_files.append(team_b_logo_path)
                try:
                    team_b_logo_clip = ImageClip(team_b_logo_path)
                    team_b_logo_clip = team_b_logo_clip.resize((logo_size, logo_size)).set_duration(video.duration)
                    # 添加一些动画效果
                    team_b_logo_clip = team_b_logo_clip.set_position(
                        lambda t: (width * 3 // 4 - logo_size // 2, height * 5 // 8)
                    )
                    logo_clips.append(team_b_logo_clip)
                except Exception as e:
                    print(f"处理队伍B视频图标时出错: {e}")
        
        # 合成最终视频
        final_clips = [video] + text_clips + logo_clips
        final_video = CompositeVideoClip(final_clips)
        
        # 添加淡入淡出效果
        final_video = final_video.fadein(0.5).fadeout(0.5)
        
        # 确保输出目录存在
        output_dir = os.path.dirname(output_path)
        if output_dir:
            os.makedirs(output_dir, exist_ok=True)
        
        # 输出视频
        print(f"正在生成视频: {output_path}")
        final_video.write_videofile(output_path, codec='libx264', audio_codec='aac')
        
        # 清理临时文件
        for temp_file in temp_files:
            if os.path.exists(temp_file):
                os.remove(temp_file)
            
        return True
    except Exception as e:
        print(f"在视频上添加文本和图标时出错: {e}")
        # 清理临时文件
        for temp_file in temp_files:
            if os.path.exists(temp_file):
                os.remove(temp_file)
        return False


def main():
    """
    主函数 - 演示如何使用add_text_and_logos_to_video函数
    """
    # 示例视频路径（请根据实际情况修改）
    video_path = r"\\Fw-152\e\媒体部素材\海报类\海报推单产出_TEST\videos\2025_11_10 AM 01-45-00_Đức_vs_Luxembourg.mp4"
    
    # 输出视频路径
    output_path = r"\\Fw-152\e\媒体部素材\海报类\海报推单产出_TEST\videos\2025_11_10 AM 01-45-00_Đức_vs_Luxembourg_with_text.mp4"
    
    # 示例比赛信息（请根据实际情况修改）
    match_info = {
        'team_a': 'Đức',  # 德国
        'team_b': 'Luxembourg',  # 卢森堡
        'match_time': '2025-11-10 01:45 AM',
        'copywriting': 'NHẬN DỮ LIỆU VÀ PHÂN TÍCH TRÒ CHƠI',  # 接收数据并分析游戏
        'team_a_logo': '',  # 球队A图标(base64格式) - 可选
        'team_b_logo': ''   # 球队B图标(base64格式) - 可选
    }
    
    print(f"正在处理视频: {video_path}")
    print(f"输出路径: {output_path}")
    print(f"比赛信息: {match_info}")
    
    # 在视频上添加文本和图标
    success = add_text_and_logos_to_video(video_path, output_path, match_info)
    
    if success:
        print("视频处理成功!")
    else:
        print("视频处理失败!")


if __name__ == "__main__":
    main()


def create_text_image_on_background(text, font_size=40, text_color=(255, 255, 255), 
                                   stroke_color=(0, 0, 0), stroke_width=1, max_width=None,
                                   background_color=(0, 0, 0, 0), padding=20):
    """
    在指定背景上创建带有文本和emoji的图像
    
    Args:
        text (str): 要绘制的文本
        font_size (int): 字体大小
        text_color (tuple): 文本颜色 (R, G, B) 或 (R, G, B, A)
        stroke_color (tuple): 描边颜色 (R, G, B) 或 (R, G, B, A)
        stroke_width (int): 描边宽度
        max_width (int): 最大宽度，超过此宽度将自动换行
        background_color (tuple): 背景颜色 (R, G, B) 或 (R, G, B, A)
        padding (int): 文本与图像边缘的间距
        
    Returns:
        PIL.Image: 生成的带文本图像
    """
    if not PIL_AVAILABLE:
        return None
    
    # 创建一个较大的画布以容纳文本
    dummy_img = Image.new('RGBA', (1000, 200), color=background_color)
    dummy_draw = ImageDraw.Draw(dummy_img)
    
    # 尝试使用支持Unicode的字体
    font = None
    try:
        # 优先使用Noto Color Emoji字体来更好地支持emoji
        noto_color_emoji_path = "C:\\Windows\\Fonts\\NotoColorEmoji.ttf"
        seguiemj_path = "C:\\Windows\\Fonts\\seguiemj.ttf"  # Segoe UI Emoji
        arialuni_path = "C:\\Windows\\Fonts\\ARIALUNI.TTF"
        segoeui_path = "C:\\Windows\\Fonts\\segoeui.ttf"
        noto_sans_paths = [
            "C:\\Windows\\Fonts\\NotoSans-Bold.ttf",
            "C:\\Windows\\Fonts\\NotoSans.ttf",
            "C:\\Windows\\Fonts\\NotoSans-Regular.ttf"
        ]
        
        # 检查可用的字体，按优先级排序 (Noto Color Emoji优先)
        font_paths = [
            noto_color_emoji_path,
            seguiemj_path,
            arialuni_path,
            segoeui_path
        ] + noto_sans_paths
        
        # 尝试加载支持emoji的字体
        for font_path in font_paths:
            if os.path.exists(font_path):
                try:
                    font = ImageFont.truetype(font_path, font_size)
                    break
                except Exception as e:
                    print(f"加载字体 {font_path} 失败: {e}")
                    continue
        
        # 如果上述字体都不可用，尝试使用随机字体
        if font is None:
            try:
                from src.utils.font_utils import get_random_font
                font = get_random_font(font_size)
            except ImportError:
                print("无法导入font_utils模块，将使用默认字体")
                font = ImageFont.load_default()
    except Exception as e:
        print(f"加载字体失败: {e}，将使用默认字体")
        font = ImageFont.load_default()
    
    # 处理自动换行，使用textwrap模块和精确的文本宽度计算
    def get_text_width(text):
        """获取文本的实际宽度"""
        try:
            bbox = dummy_draw.textbbox((0, 0), text, font=font)
            return bbox[2] - bbox[0]
        except:
            try:
                width, _ = dummy_draw.textsize(text, font=font)
                return width
            except:
                # Fallback计算方法
                return len(text) * font_size * 0.6

    def wrap_text(paragraph, max_width):
        """根据最大宽度智能换行文本"""
        # 如果整段文本宽度小于最大宽度，直接返回
        if get_text_width(paragraph) <= max_width:
            return [paragraph]
        
        lines = []
        # 按空格分割单词
        words = paragraph.split(' ')
        current_line = ""
        
        for word in words:
            # 测试添加当前单词后的行宽
            test_line = (current_line + " " + word).strip()
            line_width = get_text_width(test_line)
            
            # 如果添加单词后超过最大宽度
            if line_width > max_width:
                # 如果当前行不为空，将其作为一行添加
                if current_line:
                    lines.append(current_line)
                    current_line = word
                else:
                    # 如果当前行为空但单个单词就超过宽度，则强制换行
                    # 这里使用textwrap对长单词进行分割
                    wrapped_word = textwrap.fill(word, width=max(1, int(max_width / (font_size * 0.6))))
                    word_lines = wrapped_word.split('\n')
                    lines.extend(word_lines[:-1])  # 添加除最后一行外的所有行
                    current_line = word_lines[-1]  # 最后一行成为新的当前行
            else:
                current_line = test_line
        
        # 添加最后一行
        if current_line:
            lines.append(current_line)
            
        return lines

    # 处理所有段落
    if max_width and font:
        lines = []
        for paragraph in text.split('\n'):
            wrapped_lines = wrap_text(paragraph, max_width)
            lines.extend(wrapped_lines)
        
        wrapped_text = '\n'.join(lines)
    else:
        wrapped_text = text
    
    # 计算文本尺寸
    try:
        bbox = dummy_draw.textbbox((0, 0), wrapped_text, font=font)
        text_width = bbox[2] - bbox[0]
        text_height = bbox[3] - bbox[1]
    except:
        try:
            # fallback计算方法
            text_width, text_height = dummy_draw.textsize(wrapped_text, font=font)
        except:
            # 最后的fallback，使用估算
            lines_count = wrapped_text.count('\n') + 1
            text_width = max_width if max_width else 800
            text_height = lines_count * font_size * 1.2
    
    # 创建实际图像，增加额外空间以适应emoji和padding
    img_width = int(text_width) + stroke_width * 2 + padding * 2
    img_height = int(text_height) + stroke_width * 2 + padding * 2
    img = Image.new('RGBA', (img_width, img_height), color=background_color)
    draw = ImageDraw.Draw(img)
    
    # 绘制描边
    if stroke_width > 0:
        for x_offset in range(-stroke_width, stroke_width + 1):
            for y_offset in range(-stroke_width, stroke_width + 1):
                draw.text((stroke_width - x_offset + padding, stroke_width - y_offset + padding), 
                         wrapped_text, font=font, fill=stroke_color)
    
    # 绘制文本
    draw.text((stroke_width + padding, stroke_width + padding), 
             wrapped_text, font=font, fill=text_color)
    
    return img


def add_text_to_image(image_path, output_path, texts):
    """
    在图片上添加文本（支持emoji）
    
    Args:
        image_path (str): 原始图片路径
        output_path (str): 输出图片路径
        texts (list): 文本配置列表，每个元素为字典，包含:
            - text: 文本内容
            - position: 位置 (x, y) 或 ('center', 'center') 等
            - font_size: 字体大小
            - color: 字体颜色 (R, G, B) 或颜色名称
            - stroke_color: 描边颜色 (可选)
            - stroke_width: 描边宽度 (可选)
            - max_width: 最大宽度，超过将自动换行 (可选)
            - background_color: 文本背景颜色 (可选)
            
    Returns:
        bool: 是否成功
    """
    if not PIL_AVAILABLE:
        print("缺少必要的依赖库，请检查Pillow是否正确安装")
        return False
        
    try:
        # 检查图片文件是否存在
        if not os.path.exists(image_path):
            print(f"图片文件不存在: {image_path}")
            return False
            
        # 加载图片
        base_image = Image.open(image_path).convert("RGBA")
        
        # 处理每个文本
        for text_config in texts:
            text = text_config.get('text', '')
            position = text_config.get('position', ('center', 'center'))
            font_size = text_config.get('font_size', 40)
            color = text_config.get('color', (255, 255, 255))
            stroke_color = text_config.get('stroke_color', (0, 0, 0))
            stroke_width = text_config.get('stroke_width', 1)
            max_width = text_config.get('max_width', None)
            background_color = text_config.get('background_color', (0, 0, 0, 0))
            
            # 将颜色名称转换为RGB值
            color_map = {
                'white': (255, 255, 255),
                'black': (0, 0, 0),
                'red': (255, 0, 0),
                'green': (0, 255, 0),
                'blue': (0, 0, 255),
                'yellow': (255, 255, 0),
                'cyan': (0, 255, 255),
                'magenta': (255, 0, 255)
            }
            
            if isinstance(color, str) and color in color_map:
                color = color_map[color]
                
            if isinstance(stroke_color, str) and stroke_color in color_map:
                stroke_color = color_map[stroke_color]
            
            # 创建文本图像
            text_image = create_text_image_on_background(
                text=text,
                font_size=font_size,
                text_color=color,
                stroke_color=stroke_color,
                stroke_width=stroke_width,
                max_width=max_width,
                background_color=background_color
            )
            
            if text_image is None:
                print("创建文本图像失败")
                continue
            
            # 计算文本图像位置
            img_width, img_height = base_image.size
            text_width, text_height = text_image.size
            
            x, y = position
            if x == 'center':
                x = (img_width - text_width) // 2
            elif x == 'left':
                x = 0
            elif x == 'right':
                x = img_width - text_width
                
            if y == 'center':
                y = (img_height - text_height) // 2
            elif y == 'top':
                y = 0
            elif y == 'bottom':
                y = img_height - text_height
            
            # 将文本图像粘贴到原始图像上
            base_image.paste(text_image, (int(x), int(y)), text_image)
        
        # 保存结果
        output_dir = os.path.dirname(output_path)
        if output_dir:
            os.makedirs(output_dir, exist_ok=True)
            
        # 如果输出路径是PNG格式，则保持透明度，否则转换为RGB
        if output_path.lower().endswith('.png'):
            base_image.save(output_path, 'PNG')
        else:
            # 转换为RGB模式以兼容JPEG等格式
            rgb_image = Image.new("RGB", base_image.size, (255, 255, 255))
            rgb_image.paste(base_image, mask=base_image.split()[-1] if base_image.mode == 'RGBA' else None)
            base_image = rgb_image
            base_image.save(output_path)
            
        return True
    except Exception as e:
        print(f"在图片上添加文本时出错: {e}")
        return False
